import { AnimationEvent } from '@angular/animations';
import {
  ChangeDetectionStrategy,
  Component,
  ElementRef,
  EventEmitter,
  Input,
  OnChanges,
  OnInit,
  Output,
  Renderer2,
  ViewEncapsulation
} from '@angular/core';
import { fadeMotion, warnDeprecation, InputBoolean, ApesUpdateHostClassService } from '../core';

@Component({
  selector: 'apes-tag',
  exportAs: 'apesTag',
  preserveWhitespaces: false,
  providers: [ApesUpdateHostClassService],
  animations: [fadeMotion],
  templateUrl: './apes-tag.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
  host: {
    '[@fadeMotion]': '',
    '[@.disabled]': 'apesNoAnimation',
    '(@fadeMotion.done)': 'afterAnimation($event)',
    '(click)': 'updateCheckedStatus()',
    '[style.background-color]': 'presetColor? null : apesColor'
  }
})
export class ApesTagComponent implements OnInit, OnChanges {
  presetColor = false;
  @Input() apesMode: 'default' | 'closeable' | 'checkable' = 'default';
  @Input() apesColor: string;
  @Input() @InputBoolean() apesChecked = false;
  @Input() @InputBoolean() apesNoAnimation = false;
  @Output() readonly apesAfterClose = new EventEmitter<void>();
  @Output() readonly apesOnClose = new EventEmitter<MouseEvent>();
  @Output() readonly apesCheckedChange = new EventEmitter<boolean>();

  private isPresetColor(color?: string): boolean {
    if (!color) {
      return false;
    }
    return /^(red|orange|yellow|yellowGreen|green|darkGreen|cyan|indigo|blue|purple|magenta|pink)(-inverse)?$/.test(
      color
    );
    // return /^(pink|red|yellow|orange|cyan|green|blue|purple|geekblue|magenta|volcano|gold|lime)(-inverse)?$/.test(
    //   color
    // );
  }

  private updateClassMap(): void {
    this.presetColor = this.isPresetColor(this.apesColor);
    const prefix = 'apes-tag';
    this.apesUpdateHostClassService.updateHostClass(this.elementRef.nativeElement, {
      [`${prefix}`]: true,
      [`${prefix}-has-color`]: this.apesColor && !this.presetColor,
      [`${prefix}-${this.apesColor}`]: this.presetColor,
      [`${prefix}-checkable`]: this.apesMode === 'checkable',
      [`${prefix}-checkable-checked`]: this.apesChecked
    });
  }

  updateCheckedStatus(): void {
    if (this.apesMode === 'checkable') {
      this.apesChecked = !this.apesChecked;
      this.apesCheckedChange.emit(this.apesChecked);
      this.updateClassMap();
    }
  }

  closeTag(e: MouseEvent): void {
    this.apesOnClose.emit(e);
    if (!e.defaultPrevented) {
      this.renderer.removeChild(this.renderer.parentNode(this.elementRef.nativeElement), this.elementRef.nativeElement);
    }
  }

  afterAnimation(e: AnimationEvent): void {
    if (e.toState === 'void') {
      this.apesAfterClose.emit();
      if (this.apesAfterClose.observers.length) {
        warnDeprecation(`'(apesAfterClose)' Output is going to be removed in 9.0.0. Please use '(apesOnClose)' instead.`);
      }
    }
  }

  constructor(
    private renderer: Renderer2,
    private elementRef: ElementRef,
    private apesUpdateHostClassService: ApesUpdateHostClassService
  ) {}

  ngOnInit(): void {
    this.updateClassMap();
  }

  ngOnChanges(): void {
    this.updateClassMap();
  }
}
